package com.smart.redis.hash;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import com.smart.redis.client.RedisClient;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.ScanParams;
import redis.clients.jedis.ScanResult;

/**
 * redis 中hash的数据结构模型是
 * map<k,map<f,v>> 
 * 每个 hash 可以存储40多亿个键值对（2的32次方减1）
* @ClassName: Redis2Hash 
* @Description: TODO redis hash数据类型操作 
* @Company:e-smart.top
* @author Thinkpad 
* @version 1.0 2018年8月28日 下午5:32:58
 */
public class Redis2Hash {

	/**
	 * 
	* 
	* 删除的是k下的f-v
	* 返回删除的数量
	* 
	* @Title: hdel 
	* @Description: TODO 删除哈希表中key对应的一个或多个域 
	* @param @param key hash key
	* @param @param fields key下的字段
	* @param @return    设定文件 
	* @return Long    返回类型 
	* @throws
	 */
	public static Long hdel(String key,String... fields){
		Jedis jedis = RedisClient.getJedis();
		try {
			
			Long hdel = jedis.hdel(key, fields);
			return hdel;
		} catch (Exception e) {
			// TODO: hdel 
			System.err.println("hdel : "+e.getMessage());
			return null;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	/**
	 * 
	*
	* @Title: hexists 
	* @Description: TODO 查看key中field域对应的值是否存在 
	* @param @param key
	* @param @param field
	* @param @return    设定文件 
	* @return Boolean    返回类型 
	* @throws
	 */
	public static Boolean hexists(String key,String field){
		Jedis jedis = RedisClient.getJedis();
		try {
			
			Boolean hexists = jedis.hexists(key, field);
			return hexists;
		} catch (Exception e) {
			// TODO: hexists 
			System.err.println("hexists : "+e.getMessage());
			return false;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	/**
	 * 
	*
	* @Title: hget 
	* @Description: TODO 获取key中field域的值 
	* @param @param key
	* @param @param field
	* @param @return    设定文件 
	* @return String    返回类型 
	* @throws
	 */
	public static String hget(String key,String field){
		Jedis jedis = RedisClient.getJedis();
		try {
			
			String hget = jedis.hget(key, field);
			return hget;
		} catch (Exception e) {
			// TODO: hget 
			System.err.println("hget : "+e.getMessage());
			return null;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	/**
	 * 
	*
	* @Title: hgetAll 
	* @Description: TODO 获取key 下所有域的键值对 
	* @param @param key
	* @param @return    设定文件 
	* @return Map<String,String>    返回类型 
	* @throws
	 */
	public static Map<String, String> hgetAll(String key){
		Jedis jedis = RedisClient.getJedis();
		try {
			
			Map<String, String> hgetAll = jedis.hgetAll(key);
			return hgetAll;
		} catch (Exception e) {
			// TODO: hgetAll 
			System.err.println("hgetAll : "+e.getMessage());
			return null;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	/**
	 * 
	* field 存储的值必须是数字才能执行此操作-不能是字符串
	*
	* @Title: hincrBy 
	* @Description: TODO 给key下field域的值增加value 
	* @param @param key 键
	* @param @param field 域
	* @param @param value 增量（可正可负）
	* @param @return    设定文件 
	* @return Long    返回类型 
	* @throws
	 */
	public static Long hincrBy(String key,String field,long value){
		Jedis jedis = RedisClient.getJedis();
		try {
			
			Long hincrBy = jedis.hincrBy(key, field, value);
			return hincrBy;
		} catch (Exception e) {
			// TODO: hincrBy 
			System.err.println("hincrBy : "+e.getMessage());
			return null;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	/**
	 * 
	* field 存储的值必须是数字才能执行此操作-不能是字符串
	*
	* @Title: hincrByFloat 
	* @Description: TODO 哈希表 key 中的域 field 加上浮点数增量 value  
	* @param @param key
	* @param @param field
	* @param @param value
	* @param @return    设定文件 
	* @return Double    返回类型 
	* @throws
	 */
	public static Double hincrByFloat(String key,String field,double value){
		Jedis jedis = RedisClient.getJedis();
		try {
			
			Double hincrByFloat = jedis.hincrByFloat(key, field, value);
			return hincrByFloat;
		} catch (Exception e) {
			// TODO: hincrByFloat 
			System.err.println("hincrByFloat : "+e.getMessage());
			return null;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	/**
	 * 
	*
	* @Title: hkeys 
	* @Description: TODO 获取哈希表 key 中的所有域 
	* @param @param key
	* @param @return    设定文件 
	* @return Set<String>    返回类型 
	* @throws
	 */
	public static Set<String> hkeys(String key){
		Jedis jedis = RedisClient.getJedis();
		try {
			
			Set<String> hkeys = jedis.hkeys(key);
			return hkeys;
		} catch (Exception e) {
			// TODO: hkeys 
			System.err.println("hkeys : "+e.getMessage());
			return null;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	/**
	 * 
	*
	* @Title: hlen 
	* @Description: TODO  获取哈希表 key 中的所有域的数量 
	* @param @param key
	* @param @return    设定文件 
	* @return Long    返回类型 
	* @throws
	 */
	public static Long hlen(String key){
		Jedis jedis = RedisClient.getJedis();
		try {
			
			Long hlen = jedis.hlen(key);
			return hlen;
		} catch (Exception e) {
			// TODO: hlen 
			System.err.println("hlen : "+e.getMessage());
			return null;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	/**
	 * 
	* 不存在的 key 被当作一个空哈希表来处理，所以对一个不存在的 key 进行 HMGET 操作将返回一个只带有 nil 值的表
	* 
	* @Title: hmget 
	* @Description: TODO 获取哈希表 key 中，一个或多个给定域的值 
	* @param @param key
	* @param @param fields
	* @param @return    设定文件 
	* @return List<String>    返回类型 
	* @throws
	 */
	public static List<String> hmget(String key,String... fields){
		
		Jedis jedis = RedisClient.getJedis();
		try {
			
			List<String> hmget = jedis.hmget(key,fields);
			return hmget;
		} catch (Exception e) {
			// TODO: hmget 
			System.err.println("hmget : "+e.getMessage());
			return null;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	/**
	 * 
	*
	* @Title: hmset 
	* @Description: TODO 批量插入hash表数据 （如果hash已经存在数据，旧值会被覆盖）
	* @param @param key 键
	* @param @param map 域键值对集合
	* @param @return    设定文件 
	* @return Boolean    返回类型 
	* @throws
	 */
	public static Boolean hmset(String key,Map<String,String> map){
		Jedis jedis = RedisClient.getJedis();
		try {
			
			String hmset = jedis.hmset(key, map);
			System.out.println("hmset : "+hmset);
			return true;
		} catch (Exception e) {
			// TODO: hmset 
			System.err.println("hmset : "+e.getMessage());
			return false;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	/**
	 * 
	*
	* @Title: hset 
	* @Description: TODO 单条插入或者更新hash表数据(存在则会更新，不存在则会插入) 
	* @param @param key 键
	* @param @param field 域键
	* @param @param value 域值
	* @param @return    设定文件 
	* @return Boolean    返回类型 
	* @throws
	 */
	public static Boolean hset(String key,String field ,String value){
		Jedis jedis = RedisClient.getJedis();
		try {
			
			Long hset = jedis.hset(key, field, value);
			return hset==1l||hset==1;
		} catch (Exception e) {
			// TODO: hset 
			System.err.println("hset : "+e.getMessage());
			return false;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	/**
	 * 
	*
	* @Title: hsetnx 
	* @Description: TODO 新增一条hash 域数据（当且仅当域 field 不存在才会执行插入操作）
	* @param @param key
	* @param @param field
	* @param @param value
	* @param @return    设定文件 
	* @return Boolean    返回类型 
	* @throws
	 */
	public static Boolean hsetnx(String key,String field ,String value){
		Jedis jedis = RedisClient.getJedis();
		try {
			
			Long hsetnx = jedis.hsetnx(key, field, value);
			return hsetnx==1l||hsetnx==1;
		} catch (Exception e) {
			// TODO: hsetnx 
			System.err.println("hsetnx : "+e.getMessage());
			return false;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	/**
	 * 
	*
	* @Title: hvals 
	* @Description: TODO 获取key下所有域的值 
	* @param @param key
	* @param @return    设定文件 
	* @return List<String>    返回类型 
	* @throws
	 */
	public static List<String> hvals(String key){
		Jedis jedis = RedisClient.getJedis();
		try {
			
			List<String> hvals = jedis.hvals(key);
			return hvals;
		} catch (Exception e) {
			// TODO: hvals 
			System.err.println("hvals : "+e.getMessage());
			return null;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	/**
	 * 
	*
	* @Title: hscan 
	* @Description: TODO 查询key下所有匹配field的所有键值对集合
	* @param @param key 键
	* @param @param field 域（**field**全匹配）
	* @param @return    设定文件 
	* @return List<Entry<String,String>>    返回类型 
	* @throws
	 */
	public static List<Entry<String, String>> hscan(String key,String field){
		Jedis jedis = RedisClient.getJedis();
		try {
			String cursor = "0";
    		List<Entry<String, String>> keys = new ArrayList<Entry<String, String>>();
    		ScanParams sp = new ScanParams();
    		sp.match("*"+field+"*");//匹配规则pattern
    		sp.count(100);//每次查询数量
    		//迭代查询
    		do{
    			ScanResult<Entry<String, String>> hscan = jedis.hscan(key,cursor, sp);
                List<Entry<String, String>> result = hscan.getResult();
                if(result!=null && result.size() > 0){
                    keys.addAll(result);
                }
                //再处理cursor
                cursor = hscan.getStringCursor();
                System.out.println("cursor: "+cursor);
            }while(!cursor.equals("0"));
    		return keys;
		} catch (Exception e) {
			// TODO: hvals 
			System.err.println("hvals : "+e.getMessage());
			return null;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	public static void main(String[] args) {
//		dubbo
		System.out.println(hscan("key2","field").toString());
	}
}
